package com.example.drzhang.oengldemo.render;

import android.opengl.GLES20;
import android.util.Log;

/**
 * Created by Drzhang on 2017/11/13.
 */

public class ShaderHelper {
    private static final String TAG = ShaderHelper.class.getSimpleName();

    public static int compileVertexShader(String shaderCode) {
        return compileShader(GLES20.GL_VERTEX_SHADER, shaderCode);
    }

    public static int compileFragmentShader(String shaderCode) {
        return compileShader(GLES20.GL_FRAGMENT_SHADER, shaderCode);
    }

    /**
     * 编译着色器：顶点着色器, 片段着色器
     *
     * @param type
     * @param shaderCode
     * @return
     */
    private static int compileShader(int type, String shaderCode) {

        int shaderObjectId = GLES20.glCreateShader(type);
        if (shaderObjectId == 0) {
            Log.e(TAG, "could not create new shader");
            return 0;
        }
        //将着色器源代码上传到着色器中
        GLES20.glShaderSource(shaderObjectId, shaderCode);
        //编译上传到着色器中的源代码
        GLES20.glCompileShader(shaderObjectId);
        //得到着色器编译后的状态
        int[] compileStatus = new int[1];
        GLES20.glGetShaderiv(shaderObjectId, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

        if (compileStatus[0] == 0) {
            Log.e(TAG,GLES20.glGetShaderInfoLog(shaderObjectId));
            Log.e(TAG, "compile shader failed");
            GLES20.glDeleteShader(shaderObjectId);
            return 0;
        }

        return shaderObjectId; // 返回编译成功的着色器对象
    }

    /**
     * 链接着色器程序
     * @param vertextShaderId
     * @param fragmentSharedId
     * @return
     */
    public static int linkProgram(int vertextShaderId, int fragmentSharedId) {
        //创建着色器程序对象
        int programObjectId = GLES20.glCreateProgram();
        if (programObjectId == 0) {
            Log.e(TAG, "create program fail");
            return 0;
        }
        //将着色器添加到创建的程序中
        GLES20.glAttachShader(programObjectId, vertextShaderId);
        GLES20.glAttachShader(programObjectId, fragmentSharedId);

        GLES20.glLinkProgram(programObjectId);
        int[] linkStatus = new int[1];
        GLES20.glGetProgramiv(programObjectId, GLES20.GL_LINK_STATUS, linkStatus, 0);
        if (linkStatus[0] == 0) {
            Log.e(TAG, "link program fail, and delete program");
            GLES20.glDeleteProgram(programObjectId);
            return 0;
        }

        //链接成功
        return programObjectId;
    }

    /**
     * 验证着色器程序是否有效
     * @param program
     * @return
     */
    public static boolean validateProgram(int program){
        GLES20.glValidateProgram(program);
        int[] validateStatus = new int[1];
        GLES20.glGetProgramiv(program,GLES20.GL_VALIDATE_STATUS,validateStatus,0);
        return validateStatus[0] != 0;
    }

    /**
     * 构建着色器程序
     * @param vertexShaderSource
     * @param fragmentShaderSource
     * @return
     */
    public static int buildProgram(String vertexShaderSource, String fragmentShaderSource){
        //编译着色器代码
        int vertexShader = ShaderHelper.compileVertexShader(vertexShaderSource);
        int fragmentShader = ShaderHelper.compileFragmentShader(fragmentShaderSource);

        //将编译后的着色器代码与着色器程序进行链接
        int program = ShaderHelper.linkProgram(vertexShader, fragmentShader);

        //验证链接完成的着色器程序是否有效
        boolean validateResult = ShaderHelper.validateProgram(program);
        if (!validateResult) {
            Log.e(TAG, "program is invalid");
            return 0;
        }

        return program;
    }


}
